package com.sina.interfaces.core;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * 段浩杰   2017-09-13-10:43
 */


import com.sina.interfaces.core.domain.BaseCriteria;
import com.sina.interfaces.core.exception.InterfaceCustomException;
import com.sina.interfaces.core.exception.client.DataException;
import com.sina.interfaces.core.exception.server.InterfacesDataAccessException;
import com.sina.interfaces.core.exception.server.ResourceExistsException;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/* <p>
* 这个接口是所有 Dao 的基接口,这个设计的目的是避免为那些只有简单的 CRUD 操作的
 * 实体的类(如:记录访问的日志，只有保存和查询,日志是不能被更新的)写单独的 Dao.
 * </p>
*/
public interface BaseDao {


    /*-------- 实体公共属性名 start  -------*/

    String ID = "id";

    String VERSION = "version";

    /*-------- 实体公共属性名 end  -------*/

    /**
     * 批量操作时的数量限制
     */
    int BATCH = 20;

    Serializable save(Object entity);

    void persist(Object entity);


    void saveBatch(Collection<?> entities);


    void saveOrUpdate(Object entity);


    void update(Object entity);


    void delete(Object entity);

    <T> boolean deleteOne(Class<T> entityClass, Serializable id);

    <T> int deleteCollection(Class<T> entityClass, Collection<? extends Serializable> ids);


    <T> T get(Class<T> entityClass, Serializable id);

    /**
     * 通过唯一属性获取实体
     *
     * @param entityClass    not null
     * @param uniquePropName not null
     * @throws InterfacesDataAccessException 访问出错时抛出
     */
    <T> T getByUnique(Class<T> entityClass, String uniquePropName, Serializable uniqueProp) throws InterfacesDataAccessException;

    /**
     * @throws DataException - 当 id 为 null,或 数据不存在时
     * @see #get(Class, Serializable)
     */
    <T> T getWithException(Class<T> entityClass, Serializable id) throws DataException;

    /**
     * <p>
     * 此方法不咱们支持复合id的实体
     * </p>
     *
     * @param entityClass (not null)
     * @param id          (not null)
     * @return true 表示存在
     */
    <T> boolean isExists(Class<T> entityClass, Serializable id);

    /**
     * 通过唯一属性查询记录是否存在
     * <p>
     * 此方法不咱们支持复合id的实体
     * </p>
     *
     * @param entityClass (not null)
     * @param propName    (not null),唯一属性的名称
     * @param uniqueProp
     * @return true 表示存在
     * @throws InterfacesDataAccessException 当 propName 不存在时
     */
    <T> boolean isExistsByUnique(Class<T> entityClass, String propName, Serializable uniqueProp)
            throws InterfacesDataAccessException;

    /**
     * @param entityClass (not null)
     * @param id          若为 null 则无动作
     * @throws ResourceExistsException - 如果存在则抛出异常
     * @see #isExists(Class, Serializable)
     */
    void isExistsWithException(Class<?> entityClass, Serializable id) throws ResourceExistsException;

    <T> T load(Class<T> entityClass, Serializable id);


    /**
     * 在服务层批量操作时调用
     */
    void flushAndClear();

    void flush();

    void clear();

    void evict(Object entity);

    void refresh(Object entity);

    <T> List<T> listWithCommon(Class<T> clazz, int first, int max);

    /**
     * 不支持复合 id 的实体
     */
    <T> List<T> list(Class<T> clazz, BaseCriteria criteria);

    /**
     * 不支持复合 id 的实体
     */
    <T> long count(Class<T> clazz, BaseCriteria criteria);

    /**
     * 子接口 或子类应该 重写此方法,返回具体的实体类.
     */
    default Class<?> getEntityClass() {
        return Object.class;
    }
}